package arg

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gurkankaymak/hocon"
	"db2s/global"
	"reflect"
	"strings"
)

type rulesLevel struct {
	Mtc   int `json:"mtc"`
	Mcc   int `json:"mcc"`
	Mrc   int `json:"mrc"`
	Queue int `json:"queue"`
}

type rulesMode struct {
	Rows   reflect.Value `json:"rows"`
	Struct reflect.Value `json:"struct"`
	Object reflect.Value `json:"object"`
	HotSql reflect.Value `json:"hotSql"`
	Sync   reflect.Value `json:"sync"`
	Task   reflect.Value `json:"task"`
	Load   reflect.Value `json:"load"`
}

// 检查checkMod 参数是否设置，返回checkMod的值
func (rc *ConfigParameter) checkModGet(rules hocon.Object, Rules *RulesS) (err error) {
	var (
		modCount  int
		modeGarth map[string]any
	)
	if modeGarth, err = global.StructToMapAny(getMode()); err != nil {
		return
	}
	for k := range rules {
		if v, ok := modeGarth[k]; ok {
			modCount++
			Rules.CheckMode = k
			call := []reflect.Value{
				reflect.ValueOf(rules.ToConfig().GetObject(k).ToConfig()),
			}
			ff := v.(reflect.Value).Call(call)
			if len(ff) != 2 {
				return
			}
			if ff[1].Interface() != nil {
				err = errors.New(fmt.Sprintf("%v", ff[1].Interface()))
				return
			}
			switch k {
			case "sync":
				if ff[0].Interface() != nil {
					Rules.Sync = ff[0].Interface().(SyncS)
				}
			case "struct":
				if ff[0].Interface() != nil {
					Rules.Struct = ff[0].Interface().(StructS)
				}
			case "object":
				if ff[0].Interface() != nil {
					Rules.Object = ff[0].Interface().(ObjectS)
				}
			case "task":
				if ff[0].Interface() != nil {
					Rules.Task = ff[0].Interface().(TaskS)
				}
			case "rows":
				if ff[0].Interface() != nil {
					Rules.RowsR = ff[0].Interface().(RowsRules)
				}
			}
		}
		if modCount > 1 {
			err = errors.New(fmt.Sprintf("checkMod seeting fail. setting more than 1"))
			return
		}
	}
	return
}

// rulesSecondaryLevelParameterCheck
func rulesSecondaryLevelParameter(rules hocon.Object) (Rules RulesS, err error) {
	var (
		r  map[string]any
		s2 []string
	)
	if r, err = global.StructToMapAny(getRules()); err != nil {
		return
	} else {
		for k, v := range r {
			if r1 := rc.getHoconConfigVal(rules.ToConfig(), k, reflect.TypeOf(v).String()); r1 != nil {
				s2 = append(s2, rc.anyToJsonString(k, r1))
			} else {
				s2 = append(s2, rc.anyToJsonString(k, v))
			}
		}
	}
	jsonData := fmt.Sprintf("{%s}", strings.Join(s2, ","))
	if err = json.Unmarshal([]byte(jsonData), &Rules); err != nil {
		err = errors.New(fmt.Sprintf("rule parameter json unmarshal fail,err info is %v", err))
		return
	}
	if err = rc.checkModGet(rules, &Rules); err != nil {
		return
	}
	return
}

type rulesModeCheck struct {
	FunctionalMode    []string                 `json:"funcMode"`
	FuncPassParameter map[string]any           `json:"funcPass"`
	FuncReflect       map[string]reflect.Value `json:"funcReflect"`
}

// ruleParameterCheck
func ruleParameterCheck(p *SecondaryLevel, s rulesModeCheck) (err error) {
	var (
		schemaMap map[string]any
	)
	if schemaMap, err = global.StructToMapAny(s); err != nil {
		return
	} else {
		if v, ok := schemaMap["funcMode"]; ok {
			var funcExist bool
			for _, v1 := range v.([]string) {
				if strings.EqualFold(p.FunctionalMode, v1) {
					funcExist = true
				}
			}
			if !funcExist {
				p.RulesV.CheckMode = "rows"
				return nil
			}
		}
	}
	if p.RulesV.Mtc < 1 {
		//global.Wlog.Debug(fmt.Sprintf("(%d) %s The current parameter %s configuration error will use the default value {%d}", LogThreadSeq, Event, "cc", 10))
		p.RulesV.Mtc = 5
	}
	if p.RulesV.Mcc < 1 {
		//global.Wlog.Debug(fmt.Sprintf("(%d) %s The current parameter %s configuration error will use the default value {%d}", LogThreadSeq, Event, "rc", 50))
		p.RulesV.Mcc = 10
	}
	if p.RulesV.ChanRowCount < 1 {
		//global.Wlog.Debug(fmt.Sprintf("(%d) %s The current parameter %s configuration error will use the default value {%d}", LogThreadSeq, Event, "loc", 1000))
		p.RulesV.ChanRowCount = 1000
	}
	if p.RulesV.QueueSize < 1 {
		//global.Wlog.Debug(fmt.Sprintf("(%d) %s The current parameter %s configuration error will use the default value {%d}", LogThreadSeq, Event, "queue", 1000))
		p.RulesV.QueueSize = 10000
	}
	return
}
